/*
 * Copyright (C) 2008 xyzse
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
 * @file XInvertIndex.cc
 * @version 0.0.0
 * @author zouxin ( zouxin2008@gmail.com )
 * @date 18/3/2008 0.0.0 created, by zouxin
 */
#include <iostream>
#include <stdlib.h>
#include "XInvertIndex.h"

using namespace std;

typedef map<string,set<WordItem,itemcomp> >::value_type mapvaltype;
/*
 *inputfile:  forward.index
 *outputfile: invert.index
 */
XInvertIndex::XInvertIndex(string inputfile,string outputfile)
{
	m_input.open(inputfile.c_str(),ios::binary);
	if(!m_input)
	{
		cerr<<"can not open "<<inputfile<<endl;
		exit(-1);
	}

	m_output.open(outputfile.c_str(),ios::binary|ios::out);
	if(!m_output)
	{
		cerr<<"can not open "<<outputfile<<endl;
		exit(-1);
	}

}

XInvertIndex::~XInvertIndex()
{
	m_input.close();
	m_output.close();
}

int XInvertIndex::beginIndex()
{
	string templine;
	int docid,wordnum;
	string words;
	while(getline(m_input,templine))
	{
		//get docid
		docid=atoi(templine.c_str());
		//get wordnum
		getline(m_input,templine);
		wordnum=atoi(templine.c_str());
		//get words
		getline(m_input,templine);
		words=templine;
		//get emptyline,so as to read next doc
		getline(m_input,templine);
		
		//insert into invert index
		if(wordnum>0)
		{
		//	if(docid==0)
		//	{
			vector<TempItem>vec=getWords(words,wordnum);
			insertIndex(docid,vec);
		//	}
		}
	}

	map<string,set<WordItem,itemcomp> >::iterator mapiter;
	set<WordItem,itemcomp>::iterator setiter;
	set<WordItem,itemcomp> iset;
	for(mapiter=invertMap.begin();mapiter!=invertMap.end();mapiter++)
	{
		m_output<<(*mapiter).first<<"\n";
		iset=(*mapiter).second;
		for(setiter=iset.begin();setiter!=iset.end();setiter++)
			m_output<<setiter->docid<<"\t"<<setiter->num<<"\n";
		m_output<<"\n";
		
	}

	return 0;
}


void XInvertIndex::insertIndex(int docid,vector<TempItem> &wordvec)
{
	vector<TempItem>::iterator iter;
	map<string,set<WordItem,itemcomp> >::iterator mapiter;
	for(iter=wordvec.begin();iter!=wordvec.end();iter++)
	{
		WordItem item;
		item.docid=docid;
		item.num=iter->num;

		if((mapiter=invertMap.find(iter->word))!=invertMap.end())
		{
			(*mapiter).second.insert(item);
		}else
		{
			set<WordItem,itemcomp> setitem;
			setitem.insert(item);
			invertMap.insert(mapvaltype(iter->word,setitem));
		}
	}
	//output to file
	/*set<WordItem,itemcomp>::iterator setiter;
	set<WordItem,itemcomp> iset;
	for(mapiter=invertMap.begin();mapiter!=invertMap.end();mapiter++)
	{
		m_output<<(*mapiter).first<<"\n";
		iset=(*mapiter).second;
		for(setiter=iset.begin();setiter!=iset.end();setiter++)
			m_output<<setiter->docid<<"\t"<<setiter->num<<"\n";
		m_output<<"\n";
		
	}*/
}

//words is splited with '/',and end with '/'
vector<TempItem> XInvertIndex::getWords(string &words,int num)
{
	vector <TempItem>vec;
	vec.reserve(num);
	string::size_type pos;
	vector<TempItem>::iterator iter;
	while( (pos=words.find('/'))!=string::npos)
	{
		string newwords=words.substr(0,pos);
		////////add into vec/////
		TempItem item;
		item.word=newwords;
		item.num=1;
		if(vec.empty())
			vec.push_back(item);
		for(iter=vec.begin();iter!=vec.end();iter++)
			if(iter->word==newwords)
			{
				iter->num++;
				break;
			}else
			{
				vec.push_back(item);
				break;
			}
		/////////////
		//cout<<newwords<<endl;
		if(pos<words.length()-1)
			words=words.substr(pos+1);
		else
			break;
	}
	//debug
	/*for(iter=vec.begin();iter!=vec.end();iter++)
	{
		cout<<iter->word<<"\t"<<iter->num<<endl;
	}*/
	//
	return vec;
}
